package com.winchain.chainbill.bill.biz.discount.rx;

import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.persistence.transaction.Transaction;
import com.shell.bee.persistence.transaction.TransactionUtil;
import com.shell.framework.command.ChainBase;
import com.shell.framework.command.CommandContext;
import com.shell.framework.rx.OnErrorNotImplementedSubscriber;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.basic.charge.cmd.ValRetBizCmd;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillTranEvent;
import com.winchain.chainbill.bill.biz.contract.cmd.ContractSignCmd;
import com.winchain.chainbill.bill.biz.discount.cmd.BillDctCmd;
import com.winchain.chainbill.bill.biz.discount.cmd.BillDctRevMsgCmd;
import com.winchain.chainbill.bill.biz.discount.cmd.BillDctRevSmsCmd;
import com.winchain.chainbill.bill.biz.discount.cmd.BillDctSerFeeDebitBatchSignCmd;
import com.winchain.chainbill.bill.biz.discount.cmd.BillDctTranCmd;
import com.winchain.chainbill.bill.biz.discount.service.BillDctEventService;
import com.winchain.chainbill.bill.biz.send.cmd.BillMoveCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillOptCmd;
import com.winchain.chainbill.bill.biz.send.cmd.BillTimeoutCmd;
import com.winchain.chainbill.bill.biz.send.rx.BatchBillEvent;
import com.winchain.chainbill.bill.biz.send.vo.BatchBillStats;
import com.winchain.chainbill.chain.callback.cmd.SyncConfirmCmd;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BillDctRevPassSubscriber extends OnErrorNotImplementedSubscriber<BatchBillEvent<String, CbDct>> {
	@Autowired
	private BillTimeoutCmd<CbDct> billTimeoutCmd;
	@Autowired
	private BillOptCmd<CbDct> billOptCmd;
	@Autowired
	private BillDctCmd billDctCmd;
	@Autowired
	private BillMoveCmd<CbDct> billMoveCmd;
	@Autowired
	private BillDctTranCmd billDctTranCmd;
	@Autowired
	private SyncConfirmCmd<Bill<CbDct>> syncConfirmCmd;
	@Autowired
	private BillDctEventService billDctEventService;
	@Autowired
	private ValRetBizCmd valRetBizCmd;
	@Autowired
	private ContractSignCmd<CbDct> contractSignCmd;
	@Autowired
	private BillDctRevMsgCmd billDctRevMsgCmd;
	@Autowired
	private BillDctRevSmsCmd billDctRevSmsCmd;
	@Autowired
	private BillDctSerFeeDebitBatchSignCmd billDctSerFeeDebitBatchSignCmd;

	public void onApplicationEvent(final BatchBillEvent<String, CbDct> t) {
		List<String> records = t.getRecs();
		BatchBillStats<CbDct> stats = t.getStats();

		final Bill<CbDct> source = new Bill();
		final List<AcctTxRec> acctTxRecs = new ArrayList();
		for (final String record : records) {
			try {
				if (t.isNewTransaction()) {
					TransactionUtil.execute(new Transaction() {
						public void doInTransaction() {
							BillDctRevPassSubscriber.this.done(t, source, acctTxRecs, record);
						}
					}, new int[0]);
				} else {
					done(t, source, acctTxRecs, record);
				}
				t.setValue("acctTxRecs", acctTxRecs);
				stats.setAcctTxRecs(acctTxRecs);
				stats.addPassedRecord(source);
			} catch (Exception e) {
				e.printStackTrace();
				stats.addAbnormalRecord(source);
				stats.addAbnormalMsg(e.getMessage());
			}
		}
	}

	private void done(BatchBillEvent<String, CbDct> t, Bill<CbDct> source, List<AcctTxRec> acctTxRecs, String record) {
		BillTranEvent<CbDct> event = this.billDctEventService.getBillTranEvent(record, false);
		CbDct dct = (CbDct) event.getBill().getSource();
		event.setOperation(t.getOperation());
		event.setTimeoutOpt(t.getTimeoutOpt());
		source.setRec(event.getBill().getRec());

		boolean selfPayFee = dct.getSellerId().equals(dct.getBuyerId());
		source.setSource(dct);
		if (selfPayFee) {
			event.getOperation().setOptCode("EX18");
		}
		Bill<CbDct> prntBill = event.getBill();

		List<Bill<CbDct>> children = (List<Bill<CbDct>>) event.getChildren();

		CommandContext<Bill<CbDct>> context = new CommandContext();
		context.setSource(prntBill);
		context.setValue("Operation", t.getOperation());
		context.setValue("TimeoutOperation", t.getTimeoutOpt());

		context.setValue("bizType", "cb_dct_rev");
		context.setValue("children", children);
		context.setValue("phoneCode", t.getValue("phoneCode"));
		context.setValue("valRetBizState", "0");

		ChainBase<Bill<CbDct>> crb = new ChainBase();
		if (!ChainBillUtil.signContOnline()) {
			crb.add(this.contractSignCmd);
			crb.add(this.billDctSerFeeDebitBatchSignCmd);
		}
		crb.add(this.billTimeoutCmd);
		crb.add(this.billOptCmd);
		crb.add(this.billMoveCmd);

		crb.add(this.billDctCmd);

		crb.add(this.valRetBizCmd);
		if (!selfPayFee) {
			crb.add(this.billDctTranCmd);
			crb.add(this.syncConfirmCmd);
		}
		crb.add(this.billDctRevMsgCmd);
		crb.add(this.billDctRevSmsCmd);
		crb.execute(context);

		acctTxRecs.add((AcctTxRec) context.getValue("acctTxRec"));
		Object serFeeTxRec = context.getValue("serFeeTxRec");
		if (serFeeTxRec != null) {
			acctTxRecs.add((AcctTxRec) serFeeTxRec);
		}
	}
}
